import collections
import math

import numpy

from histogram.histcoll import HistogramCollection
from histogram.exceptions import HistogramIOError
import histogram.htypes as ht

output_fmt = '{0:.8e} {1:.8e} {2:.8e} {3:.8e}'

def dump(hin, path):
    if type(hin) == type(HistogramCollection()):
        hc = hin
    elif type(hin) in ht.htypes:
        hc = HistogramCollection()
        hc.add(hin)
    elif isinstance(hin, collections.Mapping):
        hc = HistogramCollection()
        if '__hmod__' in hin:
            hc.module_name = hin['__hmod__']
        
        for k in hin:
            if k == '__hmod__':
                continue
            hc.append(hin[k])                    

    elif isinstance(hin, collections.Sequence):
        hc = HistogramCollection(hin)
    else:
        msg = "histogram.dump() does not support output of type {0}"
        raise HistogramIOError(msg.format(type(h)))


    with open(path, 'w') as fpout:
        for k, h in enumerate(hc):
            msg = 'id ' + str(k+1)  + '\n'
            msg += 'title ' + h.name + '\n'
            msg += 'order x y dx dy\n'
            msg += 'data\n'
            for i in xrange(h.nbins):
                msg += output_fmt.format(h.bin_center(i), 
                                         h._bins[i],
                                         h.bin_width,
                                         math.sqrt(h._bins[i]))
                msg += '\n'
            msg += 'end\n'

        fpout.write(msg)



def load(path):
    with open(path, 'r') as fpin:
        idline = fpin.readline()
        tag, hid, some_number = idline.strip().split()
        tag, title    = fpin.readline().strip().split()
        tag, xlo, xhi = fpin.readline().strip().split()
        
        xlo = float(xlo)
        xhi = float(xhi)

        tag, order = fpin.readline().strip().split(None, 1)

        fields = order.split()

        tag = fpin.readline()

        all_x = []
        all_y = []
        all_dx = []
        all_dy = []
        for line in fpin:
            if 'END' in line:
                break

            x, y, dx, dy = map(float, line.split())
            
            all_x.append(x)
            all_y.append(y)
            all_dx.append(dx)
            all_dy.append(dy)
            
    
    return (numpy.asarray(all_x), numpy.asarray(all_y), 
            numpy.asarray(all_dx), numpy.asarray(all_dy))

        

